package com.lakeworks.framework.aspectj;

import com.lakeworks.common.annotation.RoleAnnotation;
import com.lakeworks.common.core.domain.entity.SysRole;
import com.lakeworks.common.core.domain.entity.SysUser;
import com.lakeworks.common.core.domain.model.LoginUser;
import com.lakeworks.common.enums.UserRoleType;
import com.lakeworks.common.exception.response.ResponseException;
import com.lakeworks.common.utils.SecurityUtils;
import com.lakeworks.mapper.SysRoleMapper;
import com.lakeworks.mapper.SysUserRoleMapper;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.LocalVariableTableParameterNameDiscoverer;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.*;
import java.util.stream.Collectors;


/**
 * 角色权限验证
 *
 * @author lakeworks
 */
@Aspect
@Component
public class RoleAspect {

    private static final Logger log = LoggerFactory.getLogger(RoleAspect.class);

    public LoginUser getLoginUser()
    {
        return SecurityUtils.getLoginUser();
    }

    @Autowired
    private SysUserRoleMapper sysUserRoleMapper;

    @Autowired
    private SysRoleMapper sysRoleMapper;


    @Pointcut("@annotation(com.lakeworks.common.annotation.RoleAnnotation)")
    private void roleCheck(){}


    @Before("roleCheck()")
    public void roleCheckFirst(JoinPoint joinPoint) throws Throwable {
        Signature signature = joinPoint.getSignature();
        MethodSignature msg=(MethodSignature) signature;
        Object target = joinPoint.getTarget();
        Method method = target.getClass().getMethod(msg.getName(), msg.getParameterTypes());
        RoleAnnotation annotation = method.getAnnotation(RoleAnnotation.class);
        UserRoleType value = annotation.value();
        System.out.println(value.getValue());
        LoginUser loginUser = getLoginUser();
        SysUser user = loginUser.getUser();
        //log.info(user.toString());
        if(user != null){
            List<Long> longs = sysUserRoleMapper.seletRoleIdByUserId(user.getUserId());
            log.info(longs.toString());
            if(!CollectionUtils.isEmpty(longs)){
                List<String> roleKeys = longs.stream().map(l -> sysRoleMapper.selectRoleById(l)).map(SysRole::getRoleKey).collect(Collectors.toList());
                if(!roleKeys.contains(value.getValue())){
                   throw new ResponseException("该用户没有权限访问，请联系管理员！");
               }
            }else {
                throw new ResponseException("当前用户没有角色！");
            }
        }else {
            throw new ResponseException("获取当前登录用户信息失败！");
        }

    }

/*

    private static String[] types = {
            "java.lang.Integer", "java.lang.Double",
            "java.lang.Float", "java.lang.Long", "java.lang.Short",
            "java.lang.Byte", "java.lang.Boolean", "java.lang.Char",
            "java.lang.String", "int", "double", "long", "short", "byte",
            "boolean", "char", "float"};
    public static Map<String,Object> getParamValue(JoinPoint joinPoint){
        Map<String, Object> map = new HashMap<String, Object>();
        //获取所有的参数
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();
        Object[] args = joinPoint.getArgs();
        for (int k = 0; k < args.length; k++) {
            Object arg = args[k];
            String typeName = arg.getClass().getTypeName();
            if (Arrays.asList(types).contains(typeName)) {
                map = getTypeValue(method,args,typeName);
            } else {
                map = getFieldsValue(arg);
            }
        }
        return map;
    }

    //获得基本类型参数map
    public static Map<String,Object> getTypeValue(Method method,Object[] args,String typeName){
        Map<String, Object> map = new HashMap<>();
        for (String t : types) {
            if (t.equals(typeName)) {
                LocalVariableTableParameterNameDiscoverer u = new LocalVariableTableParameterNameDiscoverer();
                String[] paramNames = u.getParameterNames(method);
                if (args != null && paramNames != null) {
                    for (int i = 0; i < args.length; i++) {
                        map.put(paramNames[i], args[i]);
                    }
                }
            }
        }
        return map;
    }


    //获取实体类参数map
    public static Map<String,Object> getFieldsValue(Object obj) {
        Map<String, Object> map = new HashMap<>();
        Field[] fields = obj.getClass().getDeclaredFields();
        String typeName = obj.getClass().getTypeName();
        for (Field f : fields) {
            f.setAccessible(true);
            try {
                for (String str : types) {
                    if (f.getType().getName().equals(str)) {
                        map.put(f.getName(), f.get(obj));
                    }
                }
            } catch (IllegalArgumentException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
        }
        return map;
    }
*/






   /* private static HashMap<String, Class> map = new HashMap<String, Class>() {
        {
            put("java.lang.Integer", int.class);
            put("java.lang.Double", double.class);
            put("java.lang.Float", float.class);
            put("java.lang.Long", long.class);
            put("java.lang.Short", short.class);
            put("java.lang.Boolean", boolean.class);
            put("java.lang.Char", char.class);
        }
    };
    //返回方法的参数名
    private static String[] getFieldsName(JoinPoint joinPoint) throws ClassNotFoundException, NoSuchMethodException {
        String classType = joinPoint.getTarget().getClass().getName();
        String methodName = joinPoint.getSignature().getName();
        Object[] args = joinPoint.getArgs();
        Class<?>[] classes = new Class[args.length];
        for (int k = 0; k < args.length; k++) {
            if (!args[k].getClass().isPrimitive()) {
                String result = args[k].getClass().getName();
                Class s = map.get(result);
                classes[k] = s == null ? args[k].getClass() : s;
            }
        }
        ParameterNameDiscoverer pnd = new DefaultParameterNameDiscoverer();
        Method method = Class.forName(classType).getMethod(methodName, classes);
        String[] parameterNames = pnd.getParameterNames(method);
        return parameterNames;
    }*/




     /* Map<String, Object> paramValue = getParamValue(joinPoint);
        log.info(paramValue.toString());
        if(!paramValue.isEmpty()){
            Set<Map.Entry<String, Object>> entries = paramValue.entrySet();
            for (Map.Entry<String, Object> entry:entries) {
                if(entry.getKey().equals(annotation.name())){
                    if(!String.valueOf(entry.getValue()).equals(annotation.value().getValue())){
                        throw new RuntimeException("用户角色错误，请联系管理员！");
                    }
                }
            }
        }else {
            throw new RuntimeException("用户角色获取失败！");
        }*/


}



